package com.example.lottoscratcho;

import org.andengine.engine.Engine;
import org.andengine.engine.camera.Camera;
import org.andengine.engine.handler.timer.ITimerCallback;
import org.andengine.engine.handler.timer.TimerHandler;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.scene.background.SpriteBackground;
import org.andengine.entity.sprite.ButtonSprite;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.text.Text;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.font.Font;
import org.andengine.opengl.font.FontFactory;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.atlas.bitmap.BuildableBitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.source.IBitmapTextureAtlasSource;
import org.andengine.opengl.texture.atlas.buildable.builder.BlackPawnTextureAtlasBuilder;
import org.andengine.opengl.texture.atlas.buildable.builder.ITextureAtlasBuilder.TextureAtlasBuilderException;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.texture.region.ITiledTextureRegion;
import org.andengine.opengl.texture.region.TiledTextureRegion;

import android.graphics.Typeface;

/*
 * The Scene Manager will manage both the current scene and its resources
 */
public class SceneManager {

	//the singleton instance of SceneManager 
	private static final SceneManager INSTANCE = new SceneManager();
	
//---------------------------------------------------------------------------FIELDS:

	private Scene currentScene;
//	private Scene nextScene;	//maybe...
	private MainActivity activity;
	private Engine engine;
	
	BuildableBitmapTextureAtlas textureAtlas; //may not need to be a field
	BuildableBitmapTextureAtlas backgroundTextureAtlas;
	BuildableBitmapTextureAtlas spotCoverAtlas;
	BuildableBitmapTextureAtlas timeBarAtlas;
	private ITiledTextureRegion buttonTextureRegion;
	
	Font digitFont;
	
	private TiledTextureRegion spotCoverTextureRegion;//for animation
	private TiledTextureRegion timeBarTextureRegion;
	SpriteBackground spriteBackground;

	//-------------------------SPLASH:
	private ITextureRegion thriveLogo;
	//-------------------------SC_ALPHA:
	private ITextureRegion spotBackDrop; //temporary!
	private ITextureRegion backgroundImg; //temporary!
	

//--------------------------------------------------------------------------METHODS:
	
	public Scene createScene(Scenes toCreate) {

		switch(toCreate) {
		
		case MENU:
			return createMenu();
		
		case SC_ALPHA:
			return createScratchCardAlpha();
			
		case SPLASH:
			return createSplash();
			
		default:
			System.out.println("Trying to create a scene that doesn't exist!");
			return null;
		
		}
		
	}
	
	public static void setUpSceneManager(MainActivity activity, 
										  Engine engine, 
										  Camera camera) {
		
		INSTANCE.activity = activity;
		INSTANCE.engine = engine;
		
	}
	
	public void loadResources(Scenes toLoad) {
		
		System.out.println("loading resources!");
		
		switch(toLoad) {
		
		case MENU:
			loadMenu();
			break;
		
		case SC_ALPHA:
			loadScratchCardAlpha();
			break;
			
		case SPLASH:
			System.out.println("Loading Splash!");
			loadSplash();
			break;
			
		default:
			System.out.println("Trying to load resources for a scene that doesn't exist!");
		
		}
		
	}

	public void populateScene(Scenes toPopulate) {

		switch(toPopulate) {
		
		case MENU:
			populateMenu();
			break;
		
		case SC_ALPHA:
			populateScratchCardAlpha();
			break;
			
		case SPLASH:
			populateSplash();				
			break;
			
		default:
			System.out.println("Trying to populate a scene that doesn't exist!");
		
		}
		
		
	}
		
	public void switchScenes(Scenes nextScene) {
		
		Scene newScene = createScene(nextScene);
		
		//Update the current scene
		engine.setScene(newScene);
		currentScene = newScene;
		
		loadResources(nextScene);
		populateScene(nextScene);
		
	}
	
//--------------------------------------------------------------------------MENU:

	/**
	 * Creates a new Scene for main menu
	 * @return New Main Menus Scene
	 */
	private Scene createMenu() {
		
		Scene newScene = new Scene();
		
		newScene.setBackground(new Background(0, 1, 0));
		
		//Enable touch area binding for our buttons
		newScene.setTouchAreaBindingOnActionDownEnabled(true);
				
		return newScene;
	}
	
	/**
	 * Loads the resources for the Menu scene
	 */
	private void loadMenu() {

		//Prepare a texture atlas to fit 512 x 64 pixel region
		textureAtlas = textureAtlas(512, 62);

		
		//Create a new tiled texture region with picture
		buttonTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(textureAtlas,
																					 	  activity.getAssets(),
																					 	  "button_tiles.png",	
																					 	  2, 1);				//rows, columns
	
		//Build the new atlas	
		try {
			
			textureAtlas.build(new BlackPawnTextureAtlasBuilder<IBitmapTextureAtlasSource, 
																BitmapTextureAtlas>(0, 0, 0));
			
		} catch (TextureAtlasBuilderException e) {
			
			System.out.println("Failed building button tiles");
			e.printStackTrace();
		}
		
		//Load it
		textureAtlas.load();
		
	}
	
	/**
	 * Populates Menu with appropriate Entities
	 */
	private void populateMenu() {
		
		//create our button sprite
		ButtonSprite buttonSprite = new ButtonSprite(MainActivity.CAMERA_WIDTH * 0.5f,
													 MainActivity.CAMERA_HEIGHT * 0.5f,
													 buttonTextureRegion,
													 engine.getVertexBufferObjectManager()){
		
			//Override onAreaTouched event (button sprite method)
			@Override
			public boolean onAreaTouched(TouchEvent touchEvent,
										 float touchedX,
										 float touchedY) {
				
				//If sprite touched with finger:
				if (touchEvent.isActionUp()) {
					
					//go to the first card
					switchScenes(Scenes.SC_ALPHA);
					
				}
				
				//This will swap the tiled texture region to pressed
				return super.onAreaTouched(touchEvent, touchedX, touchedY);
			}
		};
		
		//Register sprite as touchable entity
		currentScene.registerTouchArea(buttonSprite);
		
		//Put it on the Scene
		currentScene.attachChild(buttonSprite);
				
	}
	
//-------------------------------------------------------------SCRATCH CARD ALPHA:
	
	/**
	 * Creates a new Scene for SC_ALPHA
	 * @return New ScratchCardAlpha Scene
	 */
	private Scene createScratchCardAlpha() {
		
		Scene newScene = new Scene();
		
		newScene.setBackground(new Background(0, 0, 1));
		
		return newScene;
	}
	
	/**
	 * Loads the resources for the Splash scene
	 */
	private void loadScratchCardAlpha() {

		System.out.println("loading resources for scratch card alpha");
		
		loadBoringDigitFont();
		
		//Create image atlases
		textureAtlas = textureAtlas(64, 64); //(1024, 1024);
		spotCoverAtlas = textureAtlas(128, 256); //n(1024, 1024);
		timeBarAtlas = textureAtlas(256, 256); //(1024, 1024); 
		backgroundTextureAtlas = textureAtlas(1024, 2048);
		
		//load images onto atlases 
		spotBackDrop = textureRegion(textureAtlas, "backdrop.png");
		backgroundImg = textureRegion(backgroundTextureAtlas, "background.png");
			
		spotCoverTextureRegion = tiledTextureRegion(spotCoverAtlas, "face_box_tiled.png", 2, 1);
		timeBarTextureRegion = tiledTextureRegion(timeBarAtlas, "timebar.png", 3, 1);

		//Build texture atlas (put everything together)
		buildAtlas(textureAtlas);
		buildAtlas(backgroundTextureAtlas);
		buildAtlas(spotCoverAtlas);
		buildAtlas(timeBarAtlas);
		
		backgroundTextureAtlas.load();
		textureAtlas.load();
		spotCoverAtlas.load(); //Changed
		timeBarAtlas.load();
		
	}
		
	/**
	 * Populates Scratch Card Alpha with appropriate Entities
	 */
	private void populateScratchCardAlpha() {
		
		Sprite bgSprite = new Sprite(0, 0,
									 backgroundImg, 
									 engine.getVertexBufferObjectManager());
		
		SpriteBackground background = new SpriteBackground(0, 0, 0, bgSprite); 	
		
		currentScene.setBackground(background);
		currentScene.setBackgroundEnabled(true);
		
		GameManager.getInstance().loadNewCard(currentScene);
		
	}
	
//--------------------------------------------------------------------------SPLASH:

	/**
	 * Creates a new Scene for Splash
	 * @return New Scene
	 */
	private Scene createSplash() {
		
		//Create Scene object
		Scene newScene = new Scene();

		newScene.setBackground(new Background(1, 1, 1));
		
		//This is the only time createANYTHING will actually set the current scene
		currentScene = newScene;
		
		return newScene;
		
	}
	
	/**
	 * Loads the resources for the Splash scene
	 */
	private void loadSplash() {
		
		//Tells the Atlas Factory where we're keeping our graphics
		BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("graphics/");	
		//Create a new atlas 
		textureAtlas = textureAtlas(1024, 512);
		//Put Logo on it		
		thriveLogo = textureRegion(textureAtlas, "ThriveLogo.png");
		//Build atlas
		buildAtlas(textureAtlas);

		textureAtlas.load();
		
	}
	
	/**
	 * Populates Splash scene appropriate Entities
	 */
	private void populateSplash() {
		
		//create sprite
		Sprite logo = new Sprite(MainActivity.CENTER_X - 372, //logo width = 744
								 MainActivity.CENTER_Y - 152, //logo height = 285
								 thriveLogo, 
								 engine.getVertexBufferObjectManager());		
		

		
		//Place sprite into scene
		currentScene.attachChild(logo);
		
		//Creates a TimerHandler that will change scenes after 3 seconds
		engine.registerUpdateHandler(new TimerHandler(3f, new ITimerCallback() {		//This will normally wait until all resources are loaded
			
			@Override
			public void onTimePassed(TimerHandler timerHandler) {
				
				System.out.println("Time has passed and I'm switching scenes!");
				
				//Remove unneeded handler to free resources
				engine.unregisterUpdateHandler(timerHandler);
				
				switchScenes(Scenes.MENU);
				 
			}
			
		}));
		
	}

//--------------------------------------------------------------------HELPER HELPERS:
	
	/**
	 * Sets global digitFont to handle digits and loads it
	 */
	private void loadBoringDigitFont() {
		
		//create font resource
		digitFont = FontFactory.create(engine.getFontManager(),
								  engine.getTextureManager(),
								  256, 256,
								  Typeface.create(Typeface.DEFAULT, Typeface.NORMAL),
								  32f, true);
		
		//tell it what numbers/letters it will need to use
		digitFont.prepareLetters("1234567890".toCharArray());
		
		digitFont.load();
		
	}
	
	void makeMatchCardText(float xPos, float yPos, int value) {
		
		Text text = new Text(xPos, yPos, digitFont, "123456890", engine.getVertexBufferObjectManager()) {
			
		};
		text.setText("" + value);
		currentScene.attachChild(text);
		
	}
		
	/**
	 * Attaches a new SpotCover to fixture
	 * @param toBuild
	 * @return 
	 */
	public void makeMatchCardSpotCover(float x, float y, MatchCard matchCard) {
		
		SpotCover spotCover = new SpotCover(spotCoverTextureRegion, x, y, activity, matchCard);
		currentScene.attachChild(spotCover.cover);
		currentScene.registerTouchArea(spotCover.cover);
		currentScene.setTouchAreaBindingOnActionDownEnabled(true);
		
	}
	//createMatchCardBackDrop(float x, float y, Entity fixture) {...}	 //we'll probably just feed in the currentScene to this
	
	public void makeMatchCardTimeBar(float x, float y) {
		
		TimeBar timeBar = new TimeBar(timeBarTextureRegion, x, y, activity);
		timeBar.startTimeBar(300);
		currentScene.attachChild(timeBar.timebar);
		currentScene.registerTouchArea(timeBar.timebar);
		currentScene.setTouchAreaBindingOnActionDownEnabled(true);
	}

//---------------------------------------------------------------GETTERS AND SETTERS:
	
	public ITextureRegion getBackdrop() {
		return spotBackDrop;
	}
	
	public Engine getEngine() {
		return engine;
	}
	
	public static SceneManager getInstance() {
		
		return INSTANCE;
		
	}
	
	public Scene getScene() {
		return currentScene;
	}
	
	//--------------------------------------------------------------------------WRAPPERS:
	
	void buildAtlas(BuildableBitmapTextureAtlas toBuild) {
			
		try {
			toBuild.build(
					new BlackPawnTextureAtlasBuilder<IBitmapTextureAtlasSource, 
													 BitmapTextureAtlas>(1, 1, 1) );
		} 
		catch (TextureAtlasBuilderException e) {
			System.out.println("Problem building texture atlas");
			e.printStackTrace();
		}
		
	}

	/**
	 * Returns a new BuildableBitmapTextureAtlas with the current engine's TextureManager
	 * @param width
	 * @param height
	 * @return
	 */
	private BuildableBitmapTextureAtlas textureAtlas(int width, int height) {
			
		return new BuildableBitmapTextureAtlas(engine.getTextureManager(), 				//engine is global variable omitted from arguments 
												width, height);
		
	}
	
	/**
	 * Returns a new TiledTextureRegion
	 * @param tiledTextureAtlas
	 * @param path
	 * @param numColumns
	 * @param numRows
	 * @return
	 */
	private TiledTextureRegion makeTiledTextureRegion(BuildableBitmapTextureAtlas tiledTextureAtlas,
													 String path, int numColumns, int numRows) {
		
		return BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(tiledTextureAtlas, 
																		   activity,
																		   path,
																		   numColumns,
																		   numRows);
		
	}
	
	/**
	 * BitmapTextureAtlasTextureRegionFactory.createFromAsset() wrapper
	 */
	private ITextureRegion textureRegion(BuildableBitmapTextureAtlas textureAtlas, 
										 String path) {
		
		return BitmapTextureAtlasTextureRegionFactory.createFromAsset(textureAtlas, 
																	  activity, 		//global variable omitted from arguments 
																	  path);
		
	}
		
	/**
	 * BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset() wrapper
	 */
	private TiledTextureRegion tiledTextureRegion(BuildableBitmapTextureAtlas tiledTextureAtlas,
													 String path, int numColumns, int numRows) {
		
		return BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(tiledTextureAtlas, 
																		   activity,
																		   path,
																		   numColumns,
																		   numRows);
		
	}
	
}
